package tailf

import (
	"errors"
	"fmt"
	"log"
	"log-agent/conf"
	"strings"
)

type TaskManager struct {
	tasks []*TailFileTask
}

// Add 添加任务
func (tm *TaskManager) Add(task *TailFileTask) {
	tm.tasks = append(tm.tasks, task)
}

// Remove 删除任务
func (tm *TaskManager) Remove(task *TailFileTask) (bool, error) {
	index, err := tm.Contains(task.Filename)
	if err != nil {
		return false, err
	}
	tm.tasks = append(tm.tasks[:index], tm.tasks[index+1:]...)
	return true, nil
}

// Contains 判断包含
func (tm *TaskManager) Contains(taskName string) (int, error) {
	if len(tm.tasks) == 0 {
		return -1, errors.New("任务管理器为空")
	}
	for i, t := range tm.tasks {
		if t.Filename == taskName {
			return i, nil
		}
	}
	return -1, errors.New(fmt.Sprintf("%s 任务不存在", taskName))
}

// Size 任务数量
func (tm *TaskManager) Size() int {
	return len(tm.tasks)
}

func (tm *TaskManager) String() string {
	var res = strings.Builder{}
	res.WriteString(fmt.Sprintf("当前存在%d个收集任务\n", tm.Size()))
	for i, task := range tm.tasks {
		res.WriteString(fmt.Sprintf("\t-> %d:%s\n", i+1, task.Filename))
	}
	res.WriteString("\n")
	return res.String()
}

// EvictDeletingTask 剔除已经删除的收集任务
func (tm *TaskManager) EvictDeletingTask(configs []*conf.Pair) {
	var paths = make(map[string]struct{}, 64)
	for _, config := range configs {
		paths[config.Path] = struct{}{}
	}

	for _, task := range tm.tasks {
		// 新配置中不存在的要删除
		if _, exists := paths[task.Filename]; exists {
			continue
		}

		log.Printf("--> 准备删除收集任务 %s \n", task.Filename)
		// task.Filename 已经删除, 需要关闭当前在监听的文件
		task.Stop() // ctx.Done()
		// 移除任务管理器
		tm.Remove(task)
	}
}

// AddNotExistingTask 添加不存在的收集任务
func (tm *TaskManager) AddNotExistingTask(configs []*conf.Pair) {
	for _, pair := range configs {
		index, err := tm.Contains(pair.Path)
		// 已存在的不需要处理
		if err != nil {
			continue
		}
		if index == -1 {
			// 不存在的创建并添加
			log.Printf("--> 准备创建收集任务 %s \n", pair.Path)
			tailFileTask, err := New(pair.Path, pair.BufferSize)
			if err != nil {
				log.Printf("创建新收集任务 %s 失败, 错误信息: %v\n",
					pair.Path, err)
				continue
			}
			tm.Add(tailFileTask)
			go tailFileTask.Start()
		}
	}
}

func NewTaskManager() *TaskManager {
	return &TaskManager{
		tasks: make([]*TailFileTask, 0, 20),
	}
}
